﻿using System;
using System.Windows.Forms;
using System.Drawing;
using System.Drawing.Printing;
using System.ComponentModel;

using System.Runtime.InteropServices;
using System.IO;
using System.Text.RegularExpressions;
using System.Collections.Generic;
using ELookintoTXWordControl;
using System.Text;
 

namespace ILookintoControl
{
    public class TXTextControlExtension : TXTextControl.TextControl //RichTextBox
    {
        //public String SelectedText;
        
        public String Rtf;
        public String SelectedRtf;
         string BOOK_MARK_PATH = ActiveXUserControl.USER_APP_PATH + "bookmarks\\";
         string COMMENT_PATH = ActiveXUserControl.USER_APP_PATH + "comments\\";

        String localData;
        ToolTip tip;

       
        public TXTextControlExtension()
        {
            if (!Directory.Exists(BOOK_MARK_PATH))
            {
                Directory.CreateDirectory(BOOK_MARK_PATH);
            }
            if (!Directory.Exists(COMMENT_PATH))
            {
                Directory.CreateDirectory(COMMENT_PATH);
            }
            ViewMode = TXTextControl.ViewMode.PageView;
            //ViewMode = TXTextControl.ViewMode.Normal;

           localData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
            

            tip = new ToolTip();
            //tip.IsBalloon = true;
  
            ContextMenu cm = new ContextMenu();

            MenuItem mi = new MenuItem("Insert bookmark");
            mi.Click += new EventHandler(insertBookmarks);
            cm.MenuItems.Add(mi);

            mi = new MenuItem("Delete bookmark");
            mi.Click += new EventHandler(deleteBookmark);
            cm.MenuItems.Add(mi);

            mi = new MenuItem("Add Comment");
            mi.Click += new EventHandler(addComment);
            cm.MenuItems.Add(mi);

            mi = new MenuItem("Cut");
            mi.Click += new EventHandler(mi_Cut);
            cm.MenuItems.Add(mi);

            mi = new MenuItem("Copy");
            mi.Click += new EventHandler(mi_Copy);
            cm.MenuItems.Add(mi);

            mi = new MenuItem("Paste");
            mi.Click += new EventHandler(mi_Paste);
            cm.MenuItems.Add(mi);

            mi = new MenuItem("About TXElookinto");
            mi.Click += new EventHandler(mi_About);
            cm.MenuItems.Add(mi);
            this.ContextMenu = cm;

            //-- this.LinkClicked += new System.Windows.Forms.LinkClickedEventHandler(Link_Clicked);
            //this.OnMouseClick + new 


        }
        
     

        public  ELookintoTXWordControl.ActiveXUserControl axControl;


      
        protected void Link_Clicked(object sender, System.Windows.Forms.LinkClickedEventArgs e)
        {
            System.Diagnostics.Process.Start(e.LinkText);
        }

      

        /*protected override void OnClick(EventArgs e) {
            MessageBox.Show("tx");
        } */
        //Convert the unit used by the .NET framework (1/100 inch) 
        //and the unit used by Win32 API calls (twips 1/1440 inch)
       

        private const int WM_USER = 0x0400;
        private const int EM_FORMATRANGE = WM_USER + 57;

        [DllImport("USER32.dll")]
        private static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wp, IntPtr lp);


       
        Point loc = new Point(0, 0);
        protected override void OnMouseDown(MouseEventArgs e)
        {
            MouseEventArgs me = (MouseEventArgs)e;
            loc = me.Location;
            //MessageBox.Show(me.Location.ToString());
        }

        bool show = false;
       
       
        protected override void OnMouseMove(MouseEventArgs e)
        {
            
           /* MouseEventArgs me = (MouseEventArgs)e;

            //int p = this.g(me.Location);
           //TXTextControl.InputPosition ip = new TXTextControl.InputPosition(me.Location);
            int p = InputPosition.TextPosition;
           
            bool toshow = false;
            foreach(KeyValuePair<String, String[]> kv in commentDict)
            {
                this.axControl.sitelink.Text = p + " ..." + kv.Value[0] + "..."+ kv.Value[1];
                if (Int32.Parse(kv.Value[0]) <= p && p<= Int32.Parse(kv.Value[0]) + Int32.Parse(kv.Value[1]))
                {
                     //MessageBox.Show(Wrap(kv.Value[2], 30));
                    toshow = true;
                    if (show) break;

                    Point pp = this.Location;
                   // tip.Show( Wrap(kv.Value[2], 30), this, me.Location.X, me.Location.Y- 35);

                    show = true;
                    toshow = true;
                    
                    return;
                }
            }
            if (!toshow)
            {

                show = false;
                tip.Hide(this);
                
            }*/
        }

       

        Dictionary<String, String[]> bookMarkDict = new Dictionary<String, String[]>();
        Dictionary<String, String[]> commentDict = new Dictionary<String, String[]>();
        InputBoxValidation validation = delegate(string val)
        {
            if (val == "")
                return "Value cannot be empty.";
            if (!(new Regex(@"\w+")).IsMatch(val))
                return "Not a valid mark";
            return "";
        };


        void addComment(object sender, EventArgs e)
        {
            
            String value = this.Selection.Text;
            String text = value;
            String start = this.Selection.Start + "";
            String length = this.Selection.Length + "";
            if (InputBox.Show("Enter your comment", "Comment:", ref value, validation) == DialogResult.OK)
            {

                commentDict[text] = new String[] { start, length, value };
                this.Selection.TextBackColor = Color.LightGreen;
                
                persitComment();
            }
        }

       

        void insertBookmarks(object sender, EventArgs e)
        {

            String value = this.Selection.Text;
            String text = value;
            String start = this.Selection.Start + "";
            String length = this.Selection.Length + "";
           
            if (this.axControl.bookMarkCombo.Items.Contains(value))
                value += 1;
            if (InputBox.Show("Enter your bookmark name", "Bookmark:", ref value, validation) == DialogResult.OK)
            {

                bookMarkDict[value] = new String[] { start, length, text };
               // this.Selection.Text = text;
             
                this.Selection.TextBackColor = Color.Chocolate;
               
               // TXTextControl.TextField NewField = new TXTextControl.TextField();
               // NewField.ID = value.GetHashCode();
               // MessageBox.Show(text + "  " + start + " " + length);
               // NewField.Text = this.Selection.Text;
                //this.Selection.Text = "";
                //this.TextFields.Add(NewField);
                this.axControl.bookMarkCombo.Items.Add(value);
                persitBookMark();
            }


        }
        public string HashString(string Value)
        {
            System.Security.Cryptography.MD5CryptoServiceProvider x = new System.Security.Cryptography.MD5CryptoServiceProvider();
            byte[] data = System.Text.Encoding.ASCII.GetBytes(Value);
            data = x.ComputeHash(data);
            string ret = "";
            for (int i = 0; i < data.Length; i++)
                ret += data[i].ToString("x2").ToLower();
            return ret;
        }

        public void readBookMark()
        {
            try
            {
                String persistence = this.HashString(this.Text);
                // create reader & open file
                TextReader tr = new StreamReader(BOOK_MARK_PATH+persistence);

                // read a line of text
                String line;
                while ((line = tr.ReadLine()) != null)
                {
                    String[] fields = line.Split(new char[] { ',' });
                    this.axControl.bookMarkCombo.Items.Add(fields[0]);
                    bookMarkDict[fields[0]] = new String[] { fields[1], fields[2], fields[3] };
                    int start = Int32.Parse(fields[1]);
                    int length = Int32.Parse(fields[2]);
                    this.Select(start, length);
                    this.Selection.TextBackColor = Color.Chocolate;
                    //--this.SelectedText = fields[3];
                }

                // close the stream
                tr.Close();
            }
            catch (Exception e) {
                MessageBox.Show(e.Message);
                System.Diagnostics.Debug.WriteLine(e.Message);
            }
        }

        private void persitBookMark()
        {
            try
            {
                String persistence = HashString(this.Text);

                TextWriter tw = new StreamWriter(BOOK_MARK_PATH + persistence);

                foreach (KeyValuePair<String, String[]> pair in bookMarkDict)
                    tw.WriteLine(pair.Key + "," + pair.Value[0] + "," + pair.Value[1] + "," + pair.Value[2]);

                // close the stream
                tw.Close();
            }
            catch (Exception e) {
                System.Diagnostics.Debug.WriteLine(e.Message);
            }

        }

        public void readComment()
        {
         try
            {
                String persistence = this.HashString(this.Text);
                // create reader & open file
                TextReader tr = new StreamReader(COMMENT_PATH + persistence+".cm");

                // read a line of text
                String line;
                while ((line = tr.ReadLine()) != null)
                {
                    String[] fields = line.Split(new char[] { '|' });
                    commentDict[fields[0]] = new String[] { fields[1], fields[2], fields[3] };
                    int start = Int32.Parse(fields[1]);
                    int length = Int32.Parse(fields[2]);
                    this.Select(start, length);
                    this.Selection.TextBackColor = Color.LightGreen;
                    //--this.SelectedText = fields[0];
                }

                // close the stream
                tr.Close();
            }
            catch (Exception e) {
                System.Diagnostics.Debug.WriteLine(e.Message);
            }
        }

       
        private void persitComment()
        {
            try
            {
                String persistence = HashString(this.Text);

                TextWriter tw = new StreamWriter(COMMENT_PATH + persistence + ".cm");

                foreach (KeyValuePair<String, String[]> pair in commentDict)
                    tw.WriteLine(pair.Key + "|" + pair.Value[0] + "|" + pair.Value[1] + "|" + pair.Value[2]);

                // close the stream
                tw.Close();
            }
            catch (Exception e) {
                System.Diagnostics.Debug.WriteLine(e.Message);
            }

        }

        String currentBookMark = "";

        void deleteBookmark(object sender, EventArgs e)
        {
            //this.GetCharFromPosition();
            currentBookMark = "";
            int i = InputPosition.TextPosition;
            //MessageBox.Show(i + loc.ToString() + this.GetCharIndexFromPosition(loc).ToString() + this.GetCharFromPosition(loc));
            int start = -1;
            int length = -1;
            String oriText = "";
            foreach (KeyValuePair<String, String[]> pair in bookMarkDict)
            {
                start = Int32.Parse(pair.Value[0]);
                length = Int32.Parse(pair.Value[1]);
                if (i >= start && i <= start + length)
                {

                    oriText = pair.Value[2];
                    currentBookMark = pair.Key;
                    break;
                }
            }
            //currentBookMark = this.axControl.bookMarkCombo.Items[this.axControl.bookMarkCombo.SelectedIndex].ToString();
            if (this.axControl.bookMarkCombo.Items.Contains(currentBookMark))

                if (InputBox.Show("Remove your book", "Bookmark:", ref currentBookMark, validation) == DialogResult.OK)
                {
                    //MessageBox.Show(value);
                    //String text = this.SelectedText;

                    this.Select(start, length);
                    //this.SelectedText = oriText;
                    this.Selection.TextBackColor = Color.White;
                    bookMarkDict.Remove(currentBookMark);
                    this.axControl.bookMarkCombo.Items.Remove(currentBookMark);
                    persitBookMark();
                }


        }
        //Code to add right click


        /// <summary>
        /// Scrolls to the current position
        /// </summary>
        
        

        public void FindBookMark(String bookMark)
        {
            if (bookMark.Equals("Bookmarks")) return;
            try
            {
                int start = Int32.Parse(bookMarkDict[bookMark][0]);
                int length = Int32.Parse(bookMarkDict[bookMark][1]);
                this.Select(start, length);
               // this.Selection.TextBackColor = Color.Chocolate;
                this.ScrollLocation = new Point(0, this.InputPosition.Location.Y);
                
            }
            catch (Exception e) {
                System.Diagnostics.Debug.WriteLine(e.Message);
            }
        }

        void mi_Cut(object sender, EventArgs e)
        {
            this.Cut();
        }
        void mi_Copy(object sender, EventArgs e)
        {
            //Graphics objGraphics;
           //Clipboard.SetData(DataFormats.Rtf, this.SelectedRtf);
            //Clipboard.Clear();
            this.Copy();
        }

        void mi_Paste(object sender, EventArgs e)
        {
            this.Paste();
            /*f (Clipboard.ContainsText(TextDataFormat.Rtf))
            {
                this.SelectedRtf = Clipboard.GetData(DataFormats.Rtf).ToString();
            }*/
        }

        void mi_About(object sender, EventArgs e)
        {
            new AboutBox().Show();


        }
       
        #region "Avoid flickering"


        private const int WM_SETREDRAW = 0x000B;
        
        private const int EM_GETEVENTMASK = (WM_USER + 59);
        private const int EM_SETEVENTMASK = (WM_USER + 69);
 
        [System.Runtime.InteropServices.DllImport("User32")]

        private static extern IntPtr SendMessage(IntPtr hWnd, int msg, int wParam, IntPtr lParam);

        IntPtr eventMask = IntPtr.Zero;

        public  IntPtr FreezeDraw()
        { //Disable drawing

            SendMessage(this.Handle, WM_SETREDRAW, 0,IntPtr.Zero);
            eventMask = SendMessage(this.Handle, EM_GETEVENTMASK, 0, IntPtr.Zero);
            return eventMask;
        }

        public void UnfreezeDraw()
        { //Enable drawing and do a redraw. 

            SendMessage(this.Handle, EM_SETEVENTMASK, 0, eventMask);

            SendMessage(this.Handle, WM_SETREDRAW, 1, IntPtr.Zero);

            this.Invalidate(true);
           

        }

        #endregion

        
        public void LoadFile(String path)
        {
            Load(path, TXTextControl.StreamType.RichTextFormat);
        }


        public static String Wrap(string text, int maxLength)
        {

            // Return empty list of strings if the text was empty
            if (text.Length == 0) return "";

            var words = text.Split(' ');
            StringBuilder lines = new StringBuilder();
            var currentLine = "";

            foreach (var currentWord in words)
            {

                if ((currentLine.Length > maxLength) ||
                    ((currentLine.Length + currentWord.Length) > maxLength))
                {
                    lines.Append(currentLine + "\n");
                    currentLine = "";
                }

                if (currentLine.Length > 0)
                    currentLine += " " + currentWord;
                else
                    currentLine += currentWord;

            }

            if (currentLine.Length > 0)
                lines.Append(currentLine + "\n");


            return lines.ToString();
        }
       
        

    }


    
   



}

